<template>
  <div class="page-container">
    <!--表格内容栏-->
    <ac-table
      ref="dataTable" 
      pkName="id" 
      :filters="filters" 
      :filterFields="filterFields"
      :columns="columns" 
      :defaultSort="defaultSort" 
      @resetForm="resetForm"
      @handleTableOperator="handleTableOperator" 
      @handleCellOperator="handleCellOperator"
    >
    </ac-table>

    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      width="600px"
      :close-on-click-modal="false"
      append-to-body
      destroy-on-close
      draggable
    >
      <el-form
        ref="dataForm"
        :model="formData"
        label-width="120px"
        :disabled="!dialogEdit"
        :rules="rules"
        :hide-required-asterisk="!dialogEdit"
        label-position="right"
      >
        <el-row>
          <el-col :span="24">
            <el-form-item label="流程名称" prop="name">
              <el-input v-model="formData.name"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="流水序名" prop="sequenceId">
              <ac-remote-select
                v-model="formData.sequenceId"
                placeholder="--请选择--"
                dataUrl="/system/sequence/queryPage"
                :pageSize="10"
                :option="{id: formData.sequenceId, name: formData.sequenceName}"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="流程排序" prop="ordinal">
              <ac-number
                v-model="formData.ordinal"
                point="0"
              ></ac-number>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="是否有效" prop="valid">
              <ac-dict-radio v-model="formData.valid" dictCode="dictYesNo" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="流程描述" prop="description">
              <el-input
                v-model="formData.description"
                type="textarea"
                :rows="5"
                auto-complete="off"
              ></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="!dialogEdit">
          <el-col :span="24">
            <el-form-item label="更新时间" prop="updateTime">
              <ac-datetime v-model="formData.updateTime"></ac-datetime>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="!dialogEdit">
          <el-col :span="24">
            <el-form-item label="创建时间" prop="createTime">
              <ac-datetime v-model="formData.createTime"></ac-datetime>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button
          v-if="dialogEdit"
          type="info"
          @click="dialogVisible=false"
        >取消</el-button>
        <el-button
          v-if="dialogEdit"
          type="primary"
          @click="submitForm"
          :loading="editLoading"
        >提交</el-button>
        <el-button
          v-if="!dialogEdit"
          type="info"
          @click="dialogVisible=false"
        >关闭</el-button>
      </template>
    </el-dialog>

    <el-dialog
      class="no-padding"
      :title="dialogFlowTitle"
      :visible="dialogFlowVisible"
      :close-on-click-modal="false"
      v-model="dialogFlowVisible"
      append-to-body
      destroy-on-close
      draggable
      fullscreen
    >
      <div class="containers" ref="content">
        <div class="canvas" ref="canvas"></div>
        <properties-view
          v-if="bpmnModeler"
          :modeler="bpmnModeler"
          :option="bpmnOption"
        ></properties-view>
      </div>
      <template #footer>
        <el-button
          type="info"
          @click="dialogFlowVisible=false"
        >取消</el-button>
        <el-button
          type="primary"
          @click="saveXML"
          :loading="editFlowLoading"
        >提交</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, nextTick } from 'vue';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import bpmnTranslate from '@/admin/bpmn/translate';
import customModule from '@/admin/bpmn/custom';
import PropertiesView from '@/admin/bpmn/properties-panel/PropertiesView.vue';

/*左边工具栏以及编辑节点的样式*/
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
import { ElMessage, ElMessageBox } from "element-plus";
import api from "@/http/api";

const filters = ref({
  code: '',
  name: ''
}); // 分页查询条件
const filterFields = ref([
  { prop: "name", label: "流程名称" },
]);
const columns = ref([
  {prop: "code", label: "流程编码", width: 120, click: true},
  {prop: "name", label: "流程名称", minWidth: 160},
  {prop: "sequenceName", label: "流水序名", minWidth: 140, sortable: false},
  {prop: "ordinal", label: "排序", width: 90},
  {prop: "valid", label: "是否有效", width: 110, type: 'dict-radio', dictCode: 'dictYesNo'},
  {prop: "updateTime", label: "更新时间", type: 'datetime', width: 160},
  {prop: "createTime", label: "创建时间", type: 'datetime', width: 160},
]); // 分页列表字段
const defaultSort = ref({}); // 分页排序

const dialogTitle = ref(''); // 新增/编辑/查看弹窗标题
const dialogVisible = ref(false); // 弹窗是否显示
const dialogEdit = ref(true); // 弹窗表单是否可编辑
const editLoading = ref(false); // 弹窗表单提交状态
const rules = ref({
  name: [{required: true, message: '请输入流程名称', trigger: 'blur'}],
  valid: [{required: true, message: '请选择是否有效', trigger: 'change'}]
}); // 弹窗表单数据验证规则
const formData = ref({}); // 弹窗表单数据

const dialogFlowVisible = ref(false);
const editFlowLoading = ref(false); // 弹窗表单提交状态
const dialogFlowTitle = ref(''); // 弹窗表单提交状态
const formFlowData = ref({}); // 弹窗表单数据

const diagramXML = ref('<?xml version="1.0" encoding="UTF-8"?>' +
  '<bpmn2:definitions id="sample-diagram" ' +
  '    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
  '    xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" ' +
  '    xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" ' +
  '    xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" ' +
  '    xmlns:di="http://www.omg.org/spec/DD/20100524/DI" ' +
  '    xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" ' +
  '    targetNamespace="http://bpmn.io/schema/bpmn">' +
  '  <bpmn2:process id="Process_1" isExecutable="false">' +
  '  </bpmn2:process>' +
  '  <bpmndi:BPMNDiagram id="BPMNDiagram_1">' +
  '    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">' +
  '    </bpmndi:BPMNPlane>' +
  '  </bpmndi:BPMNDiagram>' +
  '</bpmn2:definitions>');
const bpmnModeler = ref(null);
const bpmnOption = ref({id: ''});
const canvas = ref();
const queryForm = ref();
const dataForm = ref();
const dataTable = ref();

const resetForm = () => {
  if (queryForm.value !== undefined) {
    queryForm.value.resetFields();
  }
};

const handleCellOperator = (property, value, row) => {
  formData.value = Object.assign({}, row);
  dialogVisible.value = true;
  dialogEdit.value = false;
  dialogTitle.value = "查看";

  nextTick(() => {
    dataForm.value.clearValidate();
  });
};

const handleTableOperator = (button, row) => {
  dialogTitle.value = button.name;

  if (button.buttonType === 'editBpmn') {
    dialogFlowTitle.value = '流程配置';
    dialogFlowVisible.value = true;
    formFlowData.value = Object.assign({}, row, {button: button});
    bpmnOption.value.id = row.id;

    nextTick(() => {
      api.post(formFlowData.value.button.dataSourUrl, formFlowData.value).then(res => {
        if(res.code === '1') {
          initBpmn();
          openDiagram(res.data.xmlText || diagramXML.value);
        } else {
          ElMessage.error(res.message);
        }
      });
    });
    return;
  }

  dialogVisible.value = true;
  dialogEdit.value = true;
  if (button.buttonType === 'edit') {
    formData.value = Object.assign({}, row, {button: button});
  } else {
    formData.value = {type: '1', valid: '1', button: button};
  }

  nextTick(() => {
    dataForm.value && dataForm.value.clearValidate();
  });
};

const submitForm = () => {
  dataForm.value.validate((valid) => {
    if (valid) {
      ElMessageBox.confirm('请确认是否提交？', '提示', {type: 'info'}).then(() => {
        editLoading.value = true;
        api.post(formData.value.button.dataDestUrl, formData.value).then(res => {
          if(res.code === '1') {
            ElMessage.success(res.message);
            dialogVisible.value = false;
            dataTable.value.findPage();
          } else {
            ElMessage.error(res.message);
          }
          editLoading.value = false;
        }).catch(() => {
          editLoading.value = false;
        })
      }).catch(()=>{})
    } else {
      ElMessage.error('数据录入不正确，请重新检查！');
    }
  })
};

const initBpmn = () => {
  if (bpmnModeler.value != null) {
    bpmnModeler.value.clear();
    bpmnModeler.value = null;
  }

  bpmnModeler.value = new BpmnModeler({
    container: canvas.value,
    additionalModules: [
      customModule,
      { translate: [ 'value', bpmnTranslate ] }
    ]
  });
};

const openDiagram = async(bpmnXML) => {
  await bpmnModeler.value.importXML(bpmnXML);
  const canvas = bpmnModeler.value.get('canvas');
  canvas.zoom('fit-viewport', 'auto');
};

const saveXML = async() => {
  if (bpmnModeler.value == null) {
    ElMessage.error('流程工具未初始化！');
    return;
  }

  try {
    const { err, xml } = await bpmnModeler.value.saveXML({format: true});
    if (err) {
      ElMessage.error('流程工具生成xml出错！');
      return;
    }

    formFlowData.value = Object.assign(formFlowData.value, {xmlText: xml});
    ElMessageBox.confirm('请确认是否提交？', '提示', {type: 'info'}).then(() => {
      editFlowLoading.value = true;
      api.post(formFlowData.value.button.dataDestUrl, formFlowData.value).then(res => {
        if(res.code === '1') {
          ElMessage.success(res.message);
          dialogFlowVisible.value = false;
        } else {
          ElMessage.error(res.message);
        }
        editFlowLoading.value = false;
      }).catch(() => {
        editFlowLoading.value = false;
      });
    }).catch(()=>{});
  } catch (e) {
    ElMessage.error('流程工具生成xml出错！');
    console.log('流程工具生成xml出错！', e);
  }
};
</script>

<style scoped>
.containers {
  background-color: #ffffff;
  width: 100%;
  height: 100%;
}
.canvas {
  width: 100%;
  height: calc(100vh - 120px);
}
.canvas :deep(.bjs-powered-by) {
  display: none;
}
</style>